package com.see.domain;

import java.math.BigDecimal;
import java.net.ServerSocket;
import java.util.Comparator;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.print.attribute.standard.MediaSize.Other;

import org.slf4j.LoggerFactory;
import org.slf4j.Logger;

import com.see.server.ServerCore;
import com.see.servise.SEEServise;

public class OpenBook {
	private String product;
	private SortedSet<Order> buyBook;
	private SortedSet<Order> sellBook;
	private SEEServise seeServise;
	
	private static Logger logger = LoggerFactory.getLogger(SEEServise.class);

	public OpenBook(String product, SEEServise seeServise) {
		this.product = product;
		buyBook = new TreeSet<Order>(new Order.BuyOrder());
		sellBook = new TreeSet<Order>(new Order.SellOrder());
		this.seeServise = seeServise;
	}

	private void setProduct(String productSymbol){
		product = productSymbol;
	}

	public String getProduct() {
		return product;
	}

	public synchronized void addToBook(Order order) {
		if(order.getType() == Operation.SELL){
			sellBook.add(order);
		} else {
			buyBook.add(order);
		}
		logger.info(order + " add to book");
	}
	
	public synchronized void removeFormBook(Order order, SortedSet<Order> book) {
		book.remove(order);
		logger.info(order + " remove from book");
	}
	
	public synchronized void tryMatchOrder(Order order){
		if(order.getType() == Operation.SELL){
			match(order, buyBook);
		} else {
			match(order, sellBook);
		}
	}
	
	private void match(Order order, SortedSet<Order> book){
		
		Order iterorder = null;
		for (Iterator<Order> iterator = book.iterator(); iterator.hasNext();) {
			iterorder = iterator.next();
			
			Price orderprice = order.getPrice();
			Price interprice = iterorder.getPrice();
			
			if(order.getType() == Operation.BUY){
				if( (orderprice.equals(interprice) || orderprice.lessOrEquals(interprice) ) && order.getAmount() == iterorder.getAmount()){
					removeFormBook(iterorder, book);
					setConterPartyForMatchOrder(order, iterorder);
					sendMsgToClient(Price.getMinPrice(order.getPrice(), iterorder.getPrice()), order, iterorder);
					break;
				}
				if(orderprice.moreOrEquals(interprice) && !orderprice.compareValueAndMarket(interprice))
					break;
			} else {
				if( (orderprice.equals(interprice) || orderprice.moreOrEquals(interprice) ) && order.getAmount() == iterorder.getAmount()){
					removeFormBook(iterorder, book);
					setConterPartyForMatchOrder(order, iterorder);
					sendMsgToClient(Price.getMinPrice(order.getPrice(),iterorder.getPrice()), order, iterorder);
					break;
				}
				if(orderprice.lessOrEquals(interprice) && !orderprice.compareValueAndMarket(interprice))
					break;
				
			}

		}

	}
	
	
	private void setConterPartyForMatchOrder(Order that, Order other){
		that.setCounterparty(other.getUser());
		other.setCounterparty(that.getUser());
	}
	
	private void sendMsgToClient(BigDecimal price, Order... orders){
		for (Order order : orders) {
			order.setMatchprice(price);
			order.setMatch(true);
			logger.info(order + " match by prise " + price);
			seeServise.sendMatchOrderToClient(order);
		}
	}

}


